package com.jplus.framework.core.classscan;

import java.io.File;
import java.lang.annotation.Annotation;
import java.util.List;

import com.jplus.framework.core.ClassScanner;
import com.jplus.framework.util.ClassUtil;
import com.jplus.framework.util.FormatUtil;

/**
 * 默认类扫描器<br>
 * 有冗余，需要改进
 *
 * @author huangyong
 * @author Yuanqy
 */
public class DefaultClassScanner implements ClassScanner {

	private Class<?> castFile2Cls(String fileName) {
		// 文件名转 class,不初始化
		return ClassUtil.loadClass(fileName, false);
	}

	/**
	 * 获取包名下所有类
	 */
	public List<Class<?>> getList(String packageName) {
		return new ClassTemplate<Class<?>>(packageName) {
			@Override
			public void checkAndAddClass(String packageName, String fileName, String suffix, List<Class<?>> filelist) {
				if (suffix.equalsIgnoreCase(".class")) {
					Class<?> cls = castFile2Cls(packageName + "." + fileName);
					filelist.add(cls);
				}
			}
		}.getList();
	}

	/**
	 * 获取包名下 you指定注解的所有类
	 */
	public List<Class<?>> getListByAnnotation(String packageName, final Class<? extends Annotation> annotationClass, final boolean isRecursive) {
		return new ClassTemplate<Class<?>>(packageName) {
			@Override
			public void checkAndAddClass(String packageName, String fileName, String suffix, List<Class<?>> filelist) {
				if (suffix.equalsIgnoreCase(".class")) {
					Class<?> cls = castFile2Cls(packageName + "." + fileName);
					if (!cls.isAnnotation()) {
						if (ClassUtil.ckPresentAnno(cls, annotationClass, isRecursive)) {
							filelist.add(cls);
						}
					}
				}
			}
		}.getList();
	}

	/**
	 * 获取包名下 继承/实现某类的所有实现类,不包含自己
	 */
	public List<Class<?>> getListBySuper(String packageName, final Class<?> superClass) {
		return new ClassTemplate<Class<?>>(packageName) {
			@Override
			public void checkAndAddClass(String packageName, String fileName, String suffix, List<Class<?>> filelist) {
				if (suffix.equalsIgnoreCase(".class")) {
					Class<?> cls = castFile2Cls(packageName + "." + fileName);
					if (superClass.isAssignableFrom(cls) && !superClass.equals(cls)) {
						filelist.add(cls);
					}
				}
			}
		}.getList();
	}

	/**
	 * 获取包名下 you指定注解的所有类[满足一个注解即可]
	 */
	@Override
	public List<Class<?>> getListByAnnotation(String packageName, final List<Class<? extends Annotation>> annotationClass, final boolean isRecursive) {
		return new ClassTemplate<Class<?>>(packageName) {
			@Override
			public void checkAndAddClass(String packageName, String fileName, String suffix, List<Class<?>> filelist) {
				if (suffix.equalsIgnoreCase(".class")) {
					Class<?> cls = castFile2Cls(packageName + "." + fileName);
					if (!cls.isAnnotation()) {
						for (Class<? extends Annotation> cl : annotationClass) {
							if (ClassUtil.ckPresentAnno(cls, cl, isRecursive)) {
								filelist.add(cls);
								break;
							}
						}
					}
				}
			}
		}.getList();
	}

	/**
	 * 获取包名下 继承/实现某类的所有实现类,不包含自己。[满足一个注解即可]
	 */
	@Override
	public List<Class<?>> getListBySuper(String packageName, final List<Class<?>> superClass) {
		return new ClassTemplate<Class<?>>(packageName) {
			@Override
			public void checkAndAddClass(String packageName, String fileName, String suffix, List<Class<?>> filelist) {
				if (suffix.equalsIgnoreCase(".class")) {
					Class<?> cls = castFile2Cls(packageName + "." + fileName);
					for (Class<?> cl : superClass) {
						if (cl.isAssignableFrom(cls) && !cl.equals(cls)) {
							filelist.add(cls);
							break;
						}
					}
				}
			}
		}.getList();
	}

	/**
	 * 获取包名下 所有的xml文件
	 */
	@Override
	public List<File> getXmlFileList(String packageName) {
		return new ClassTemplate<File>(packageName) {
			@Override
			public void checkAndAddClass(String packageName, String fileName, String suffix, List<File> filelist) {
				if (suffix.equalsIgnoreCase(".xml")) {
					packageName = packageName.replaceAll("\\.", "/");
					String filePath = FormatUtil.formatPath(ClassUtil.getClassPath() + packageName + "/" + fileName + suffix);
					File file = new File(filePath);
					filelist.add(file);
				}
			}
		}.getList();
	}

	@Override
	public List<Class<?>> getListIsInterface(String packageName) {
		return new ClassTemplate<Class<?>>(packageName) {
			@Override
			public void checkAndAddClass(String packageName, String fileName, String suffix, List<Class<?>> filelist) {
				if (suffix.equalsIgnoreCase(".class")) {
					Class<?> cls = castFile2Cls(packageName + "." + fileName);
					if (cls.isInterface())
						filelist.add(cls);
				}
			}
		}.getList();
	}


}
